package com.yjhh.chdataservice.service;

import com.yjhh.chdataservice.InitDataFactory;
import com.yjhh.chdataservice.beans.*;
import com.yjhh.chdataservice.component.CommonDataComponent;
import com.yjhh.chdataservice.component.ESClientManager;
import com.yjhh.chdataservice.except.YJHHException;
import com.yjhh.chdataservice.util.CommonResultData;
import com.yjhh.chdataservice.util.DataConsts;
import com.yjhh.chdataservice.util.DataTools;
import com.yjhh.chdataservice.util.XaUtil;
import lombok.extern.log4j.Log4j;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.AbstractQueryBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter;
import org.elasticsearch.search.aggregations.bucket.filters.FiltersAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.filters.FiltersAggregator;
import org.elasticsearch.search.aggregations.bucket.filters.InternalFilters;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.sum.InternalSum;
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
import org.elasticsearch.search.aggregations.metrics.sum.SumAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.prefixQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 * Created by hlantian on 2017/9/26.
 * 辅助决策关键指标管理serviceImpl
 */
@Service
@Log4j2
public class FZJCKeyInfoServiceImpl implements FZJCKeyInfoService {

    @Autowired
    private ESClientManager esClientManager;

    @Autowired
    private InitDataFactory initDataFactory;

    @Autowired
    private CommonDataComponent commonDataComponent;


    @Override
    public CommonResultData<List<CommonNameValueVo<Double>>> getPointStartedOrEndedRate(KeyStatisticalCondVo keyStatisticalCondVo, String condField)
            throws YJHHException {
        String statisticalType = keyStatisticalCondVo.getStatisticalType();
        String cond = keyStatisticalCondVo.getCond();
        String endDate = keyStatisticalCondVo.getEndDate();
        if (StringUtils.isBlank(endDate)) {
            endDate = XaUtil.formatDate2String(new Date(), "yyyy-MM-dd");
        }

        List<CommonNameValueVo<Double>> resultList = new ArrayList<>();
        switch (statisticalType) {
            case DataConsts.StatisticalType.CITY:
                //获取子部门
                DeptBean sysDeptInfo = commonDataComponent.getSysDeptInfo(cond);
                if (sysDeptInfo == null) {
                    return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
                }
                List<DeptBean> subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());
                for (DeptBean deptBean : subDept) {
                    double startedPercent = getPlacementPointStartedPercentByCity(deptBean.getDeptno(), endDate, condField);
                    resultList.add(new CommonNameValueVo(deptBean.getDeptName(), startedPercent));
                }
                break;
            case DataConsts.StatisticalType.AREA:
                //获取子部门
                resultList = getPlacementPointStartedPercentByAreaType(commonDataComponent.getSysDeptInfo(keyStatisticalCondVo.getAreaCode())
                        .getDeptno(), endDate, cond, condField);
                break;
            default:
                return new CommonResultData<>(HttpStatus.OK.value(), "suc", null);
        }
        /*//对结果进行排序
        Collections.sort(resultList, (CommonNameValueVo<Double> o1, CommonNameValueVo<Double> o2) -> {
            return o2.getValue() <= o1.getValue() ? -1 : 1;
        });*/
        return new CommonResultData<>(HttpStatus.OK.value(), "suc", resultList);
    }

    /**
     * 按区域类型获取安置点开、竣工率
     *
     * @param deptno
     */
    private List<CommonNameValueVo<Double>> getPlacementPointStartedPercentByAreaType(String deptno, String endDate, String areaType, String
            condField) throws
            YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("a_deletestate", "0"));
        areacodequery.must(termQuery("a_ispoint", "1"));

        if (StringUtils.isNotBlank(areaType)) {
            areacodequery.must(termQuery("c_areatype.keyword", areaType));
        }

        areacodequery.must(prefixQuery("a_deptno.keyword", deptno));

        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("pl_placementpoint_inf").setTypes
                ("placementpoint_inf")
                .setSize(0);
        searchRequestBuilder.setQuery(areacodequery);

        RangeQueryBuilder rangeQueryBuilder = rangeQuery(condField);
        rangeQueryBuilder.format("yyyy-MM-dd");
        rangeQueryBuilder.lte(endDate);

        TermsAggregationBuilder areaTypeFlag = AggregationBuilders.terms("areaTypeFlag")
                .field("c_areatype.keyword").size(1000);

        FilterAggregationBuilder filterAggregationBuilder = AggregationBuilders.filter("yearTask", rangeQueryBuilder);
        areaTypeFlag.subAggregation(filterAggregationBuilder);
        searchRequestBuilder.addAggregation(areaTypeFlag);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        StringTerms stringTerms = (StringTerms) searchResponse.getAggregations().asList().get(0);
        List<StringTerms.Bucket> buckets = stringTerms.getBuckets();

        List<CommonNameValueVo<Double>> resultList = new ArrayList<>();
        for (StringTerms.Bucket bucket : buckets) {
            String key = bucket.getKeyAsString();
            long totalPoint = bucket.getDocCount();
            InternalFilter internalFilter = (InternalFilter) bucket.getAggregations().asList().get(0);

            long startedPoint = internalFilter.getDocCount();
            if (totalPoint == 0) {
                resultList.add(new CommonNameValueVo<Double>(key, 0.0));
            } else {
                BigDecimal bigDecimal = new BigDecimal(((double) startedPoint / (double) totalPoint) * 100);
                resultList.add(new CommonNameValueVo<Double>(key, bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()));
            }
        }
        return resultList;
    }

    /**
     * 按地市获取安置点开、竣工率
     *
     * @param deptno
     */
    private double getPlacementPointStartedPercentByCity(String deptno, String endDate, String condField) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("a_deletestate", "0"));
        areacodequery.must(termQuery("a_ispoint", "1"));
        areacodequery.must(prefixQuery("a_deptno.keyword", deptno));

        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("pl_placementpoint_inf").setTypes
                ("placementpoint_inf")
                .setSize(0);
        searchRequestBuilder.setQuery(areacodequery);

        RangeQueryBuilder rangeQueryBuilder = rangeQuery(condField);
        rangeQueryBuilder.format("yyyy-MM-dd");
        rangeQueryBuilder.lte(endDate);
        FilterAggregationBuilder filterAggregationBuilder = AggregationBuilders.filter("yearTask", rangeQueryBuilder);
        searchRequestBuilder.addAggregation(filterAggregationBuilder);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        Aggregations aggregations = searchResponse.getAggregations();
        InternalFilter internalFilter = (InternalFilter) aggregations.asList().get(0);

        long totalPoint = searchResponse.getHits().getTotalHits();
        long startedPoint = internalFilter.getDocCount();
        if (totalPoint == 0) {
            return 0.0;
        }
        BigDecimal bigDecimal = new BigDecimal(((double) startedPoint / (double) totalPoint) * 100);
        return bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    @Override
    public CommonResultData<List<CommonNameValueVo<Double>>> getObjTurnKeyOrMoveInRate(KeyStatisticalCondVo keyStatisticalCondVo, String condField)
            throws YJHHException {
        String statisticalType = keyStatisticalCondVo.getStatisticalType();
        String cond = keyStatisticalCondVo.getCond();
        String endDate = keyStatisticalCondVo.getEndDate();
        if (StringUtils.isBlank(endDate)) {
            endDate = XaUtil.formatDate2String(new Date(), "yyyy-MM-dd");
        }

        List<CommonNameValueVo<Double>> resultList = new ArrayList<>();
        switch (statisticalType) {
            case DataConsts.StatisticalType.CITY:
                //获取子部门
                DeptBean sysDeptInfo = commonDataComponent.getSysDeptInfo(cond);
                if (sysDeptInfo == null) {
                    return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
                }
                List<DeptBean> subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());
                for (DeptBean deptBean : subDept) {
                    double turnKeyPercent = getTurnKeyOrMoveInObjByCity(deptBean.getDeptno(), endDate, condField);
                    resultList.add(new CommonNameValueVo(deptBean.getDeptName(), turnKeyPercent));
                }
                break;
            case DataConsts.StatisticalType.AREA:
                sysDeptInfo = commonDataComponent.getSysDeptInfo(keyStatisticalCondVo.getAreaCode());
                if (sysDeptInfo == null) {
                    return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
                }
                subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());
                Map<String, Long[]> areaMap = new HashMap<>();
                for (DeptBean deptBean : subDept) {
                    Long[] longs = getTurnKeyOrMoveInObjByArea(deptBean.getDeptno(), endDate, condField);
                    String areaType = deptBean.getAreaType();   //关中、陕南、陕北,对数据进行累加
                    //过滤区域
                    if (StringUtils.isBlank(cond) || StringUtils.contains(cond, areaType)) {
                        if (areaMap.containsKey(areaType)) {
                            Long[] srcArray = areaMap.get(areaType);
                            srcArray[0] = srcArray[0] + longs[0];
                            srcArray[1] = srcArray[1] + longs[1];
                            areaMap.put(areaType, srcArray);
                        } else {
                            areaMap.put(areaType, longs);
                        }
                    }
                }

                //计算按区域分交钥匙、入住的百分比
                for (Map.Entry<String, Long[]> entry : areaMap.entrySet()) {
                    Long[] value = entry.getValue();
                    Long totalData = value[0];
                    if (totalData.longValue() == 0) {
                        new CommonNameValueVo<Double>(entry.getKey(), 0.0);
                    }
                    BigDecimal bigDecimal = new BigDecimal(((double) value[1] / (double) totalData) * 100);
                    resultList.add(new CommonNameValueVo<>(entry.getKey(), bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()));
                }
                break;
            default:
                return new CommonResultData<>(HttpStatus.OK.value(), "suc", null);
        }
        /*//对结果进行排序
        Collections.sort(resultList, (CommonNameValueVo<Double> o1, CommonNameValueVo<Double> o2) -> {
            return o2.getValue() <= o1.getValue() ? -1 : 1;
        });*/
        return new CommonResultData<>(HttpStatus.OK.value(), "suc", resultList);
    }

    @Override
    public CommonResultData<List<CommonNameValueVo<Double>>> getCentralizedRate(KeyStatisticalCondVo keyStatisticalCondVo, AbstractQueryBuilder
            query) throws YJHHException {

        String statisticalType = keyStatisticalCondVo.getStatisticalType();
        String cond = keyStatisticalCondVo.getCond();

        List<CommonNameValueVo<Double>> resultList = new ArrayList<>();
        switch (statisticalType) {
            case DataConsts.StatisticalType.CITY:
                //获取子部门
                DeptBean sysDeptInfo = commonDataComponent.getSysDeptInfo(cond);
                if (sysDeptInfo == null) {
                    return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
                }
                List<DeptBean> subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());
                for (DeptBean deptBean : subDept) {
                    double turnKeyPercent = getCentralizedRateByCity(deptBean.getDeptno(), query);
                    resultList.add(new CommonNameValueVo(deptBean.getDeptName(), turnKeyPercent));
                }
                break;
            case DataConsts.StatisticalType.AREA:
                sysDeptInfo = commonDataComponent.getSysDeptInfo(keyStatisticalCondVo.getAreaCode());
                if (sysDeptInfo == null) {
                    return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
                }
                subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());
                Map<String, Long[]> areaMap = new HashMap<>();
                for (DeptBean deptBean : subDept) {
                    Long[] longs = getCentralizedRateByArea(deptBean.getDeptno(), query);
                    String areaType = deptBean.getAreaType();   //关中、陕南、陕北,对数据进行累加
                    //过滤区域
                    if (StringUtils.isBlank(cond) || StringUtils.contains(cond, areaType)) {
                        if (areaMap.containsKey(areaType)) {
                            Long[] srcArray = areaMap.get(areaType);
                            srcArray[0] = srcArray[0] + longs[0];
                            srcArray[1] = srcArray[1] + longs[1];
                            areaMap.put(areaType, srcArray);
                        } else {
                            areaMap.put(areaType, longs);
                        }
                    }
                }

                //计算按区域分交钥匙、入住的百分比
                for (Map.Entry<String, Long[]> entry : areaMap.entrySet()) {
                    Long[] value = entry.getValue();
                    Long totalData = value[0];
                    if (totalData.longValue() == 0) {
                        new CommonNameValueVo<Double>(entry.getKey(), 0.0);
                    }
                    BigDecimal bigDecimal = new BigDecimal(((double) value[1] / (double) totalData) * 100);
                    resultList.add(new CommonNameValueVo<>(entry.getKey(), bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()));
                }
                break;
            default:
                return new CommonResultData<>(HttpStatus.OK.value(), "suc", null);
        }

/*        //对结果进行排序
        Collections.sort(resultList, (CommonNameValueVo<Double> o1, CommonNameValueVo<Double> o2) -> {
            return o2.getValue() <= o1.getValue() ? -1 : 1;
        });*/

        return new CommonResultData<>(HttpStatus.OK.value(), "suc", resultList);

    }

    @Override
    public CommonResultData<List<CommonNameValueVo<Double>>> getPerCapitaInCome(KeyStatisticalCondVo keyStatisticalCondVo) throws YJHHException {
        String statisticalType = keyStatisticalCondVo.getStatisticalType();
        String cond = keyStatisticalCondVo.getCond();

        List<CommonNameValueVo<Double>> resultList = new ArrayList<>();
        switch (statisticalType) {
            case DataConsts.StatisticalType.CITY:
                //获取子部门
                DeptBean sysDeptInfo = commonDataComponent.getSysDeptInfo(cond);
                if (sysDeptInfo == null) {
                    return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
                }
                List<DeptBean> subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());
                for (DeptBean deptBean : subDept) {
                    double turnKeyPercent = getPerCapitaInComeByAreaCode(deptBean.getDeptno());
                    resultList.add(new CommonNameValueVo(deptBean.getDeptName(), turnKeyPercent));
                }
                break;
            case DataConsts.StatisticalType.AREA:
                sysDeptInfo = commonDataComponent.getSysDeptInfo(keyStatisticalCondVo.getAreaCode());
                if (sysDeptInfo == null) {
                    return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
                }
                subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());
                Map<String, Double[]> areaMap = new HashMap<>();
                for (DeptBean deptBean : subDept) {
                    Double[] perCapitaInComeArray = getPerCapitaInComeArrayByAreaCode(deptBean.getDeptno());
                    String areaType = deptBean.getAreaType();   //关中、陕南、陕北,对数据进行累加
                    //过滤区域
                    if (StringUtils.isBlank(cond) || StringUtils.contains(cond, areaType)) {
                        if (areaMap.containsKey(areaType)) {
                            Double[] srcArray = areaMap.get(areaType);
                            srcArray[0] = srcArray[0] + perCapitaInComeArray[0];
                            srcArray[1] = srcArray[1] + perCapitaInComeArray[1];
                            areaMap.put(areaType, srcArray);
                        } else {
                            areaMap.put(areaType, perCapitaInComeArray);
                        }
                    }
                }

                for (Map.Entry<String, Double[]> entry : areaMap.entrySet()) {
                    Double[] value = entry.getValue();
                    Double totalInCome = value[0];
                    if (totalInCome.longValue() == 0) {
                        new CommonNameValueVo<Double>(entry.getKey(), 0.0);
                    }
                    BigDecimal bigDecimal = new BigDecimal((totalInCome / value[1]));
                    resultList.add(new CommonNameValueVo<>(entry.getKey(), bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()));
                }
                break;
            default:
                return new CommonResultData<>(HttpStatus.OK.value(), "suc", null);
        }
        /*//对结果进行排序
        Collections.sort(resultList, (CommonNameValueVo<Double> o1, CommonNameValueVo<Double> o2) -> {
            return o2.getValue() <= o1.getValue() ? -1 : 1;
        });*/

        return new CommonResultData<>(HttpStatus.OK.value(), "suc", resultList);
    }


    /**
     * 获取人均收入数据统计
     *
     * @return
     * @throws YJHHException
     */
    public Double getPerCapitaInComeByAreaCode(String deptno) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("isdelete", "0"));
        areacodequery.must(prefixQuery("deptno.keyword", deptno));
        areacodequery.must(existsQuery("bqhjtzsr"));
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("obj_reloca_info").setTypes("reloca_info").setSize
                (0).setQuery
                (areacodequery);

        SumAggregationBuilder totalIncomeAggs = AggregationBuilders.sum("totalInCome").field("bqhjtzsr");
        SumAggregationBuilder totalPropleNumAggs = AggregationBuilders.sum("totalPropleNum").field("familyMemberCount");
        searchRequestBuilder.addAggregation(totalIncomeAggs);
        searchRequestBuilder.addAggregation(totalPropleNumAggs);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        Aggregations aggregations = searchResponse.getAggregations();
        Map<String, Aggregation> aggMap = aggregations.asMap();
        InternalSum totalInCome = (InternalSum) aggMap.get("totalInCome");
        InternalSum totalPropleNum = (InternalSum) aggMap.get("totalPropleNum");

        if (totalInCome.value() <= 0) {
            return 0.0;
        }

        BigDecimal bigDecimal = new BigDecimal((totalInCome.value() / totalPropleNum.value()));
        return bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public Double[] getPerCapitaInComeArrayByAreaCode(String deptno) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("isdelete", "0"));
        areacodequery.must(prefixQuery("deptno.keyword", deptno));
        areacodequery.must(existsQuery("bqhjtzsr"));
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("obj_reloca_info").setTypes("reloca_info").setSize
                (0).setQuery
                (areacodequery);

        SumAggregationBuilder totalIncomeAggs = AggregationBuilders.sum("totalInCome").field("bqhjtzsr");
        SumAggregationBuilder totalPropleNumAggs = AggregationBuilders.sum("totalPropleNum").field("familyMemberCount");
        searchRequestBuilder.addAggregation(totalIncomeAggs);
        searchRequestBuilder.addAggregation(totalPropleNumAggs);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        Aggregations aggregations = searchResponse.getAggregations();
        Map<String, Aggregation> aggMap = aggregations.asMap();
        InternalSum totalInCome = (InternalSum) aggMap.get("totalInCome");
        InternalSum totalPropleNum = (InternalSum) aggMap.get("totalPropleNum");

        return new Double[]{totalInCome.value(), totalPropleNum.value()};
    }

    /**
     * 获取交钥匙和入住的户数比率统计
     */
    private Double getTurnKeyOrMoveInObjByCity(String deptno, String endDate, String condField) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("isdelete", "0"));
        areacodequery.must(prefixQuery("deptno.keyword", deptno));
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("obj_reloca_info")
                .setTypes("reloca_info").setSize(0).setQuery(areacodequery);

        RangeQueryBuilder rangeQueryBuilder = rangeQuery(condField);
        rangeQueryBuilder.format("yyyy-MM-dd");
        rangeQueryBuilder.lte(endDate);
        FilterAggregationBuilder filterAggregationBuilder = AggregationBuilders.filter("agg", rangeQueryBuilder);
        searchRequestBuilder.addAggregation(filterAggregationBuilder);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        long totalHits = searchResponse.getHits().getTotalHits();
        InternalFilter aggregation = (InternalFilter) searchResponse.getAggregations().asList().get(0);
        long docCount = aggregation.getDocCount();

        if (totalHits == 0) {
            return 0.0;
        }

        BigDecimal bigDecimal = new BigDecimal(((double) docCount / (double) totalHits) * 100);
        return bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 获取交钥匙和入住的户数比率统计
     */
    private Long[] getTurnKeyOrMoveInObjByArea(String deptno, String endDate, String condField) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("isdelete", "0"));
        areacodequery.must(prefixQuery("deptno.keyword", deptno));
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("obj_reloca_info")
                .setTypes("reloca_info").setSize(0).setQuery(areacodequery);

        RangeQueryBuilder rangeQueryBuilder = rangeQuery(condField);
        rangeQueryBuilder.format("yyyy-MM-dd");
        rangeQueryBuilder.lte(endDate);
        FilterAggregationBuilder filterAggregationBuilder = AggregationBuilders.filter("agg", rangeQueryBuilder);
        searchRequestBuilder.addAggregation(filterAggregationBuilder);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        long totalHits = searchResponse.getHits().getTotalHits();
        InternalFilter aggregation = (InternalFilter) searchResponse.getAggregations().asList().get(0);
        long docCount = aggregation.getDocCount();

        return new Long[]{totalHits, docCount};
    }

    /**
     * 获取按城市 统计集中安置比率
     */
    private Double getCentralizedRateByCity(String deptno, AbstractQueryBuilder query) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("isdelete", "0"));
        areacodequery.must(prefixQuery("deptno.keyword", deptno));
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("obj_reloca_info")
                .setTypes("reloca_info").setSize(0).setQuery(areacodequery);

        TermQueryBuilder allTermQuery = termQuery("isdelete", "0");

        FiltersAggregationBuilder filters = AggregationBuilders.filters("jizhong", new FiltersAggregator.KeyedFilter("all", allTermQuery), new
                FiltersAggregator.KeyedFilter("part", query));

        SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("peopleNum").field("familyMemberCount");

        filters.subAggregation(sumAggregationBuilder);

        searchRequestBuilder.addAggregation(filters);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        double totalHits = 0;
        double docCount = 0;
        List<Aggregation> aggregationList = searchResponse.getAggregations().asList();

        for (Aggregation aggr : aggregationList) {
            InternalFilters aggregation = (InternalFilters) aggr;
            List<InternalFilters.InternalBucket> buckets = aggregation.getBuckets();
            for (InternalFilters.InternalBucket bucket : buckets) {
                String key = bucket.getKeyAsString();
                double peopleCount = ((Sum) bucket.getAggregations().asList().get(0)).getValue();
                if ("all".equals(key)) {
                    totalHits = peopleCount;
                } else {
                    docCount = peopleCount;
                }
            }
        }

        if (totalHits == 0) {
            return 0.0;
        }

        BigDecimal bigDecimal = new BigDecimal((docCount / totalHits) * 100);
        return bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 获取按区域 统计集中安置比率
     */
    private Long[] getCentralizedRateByArea(String deptno, AbstractQueryBuilder query) throws YJHHException {
        BoolQueryBuilder areacodequery = boolQuery().must(termQuery("isdelete", "0"));
        areacodequery.must(prefixQuery("deptno.keyword", deptno));
        SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("obj_reloca_info")
                .setTypes("reloca_info").setSize(0).setQuery(areacodequery);

        TermQueryBuilder allTermQuery = termQuery("isdelete", "0");

        FiltersAggregationBuilder filters = AggregationBuilders.filters("jizhong", new FiltersAggregator.KeyedFilter("all", allTermQuery), new
                FiltersAggregator.KeyedFilter("part", query));

        SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("peopleNum").field("familyMemberCount");

        filters.subAggregation(sumAggregationBuilder);

        searchRequestBuilder.addAggregation(filters);

        log.info("request=" + searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("response=" + searchResponse.toString());

        double totalHits = 0;
        double docCount = 0;
        List<Aggregation> aggregationList = searchResponse.getAggregations().asList();

        for (Aggregation aggr : aggregationList) {
            InternalFilters aggregation = (InternalFilters) aggr;
            List<InternalFilters.InternalBucket> buckets = aggregation.getBuckets();
            for (InternalFilters.InternalBucket bucket : buckets) {
                String key = bucket.getKeyAsString();
                double peopleCount = ((Sum) bucket.getAggregations().asList().get(0)).getValue();
                if ("all".equals(key)) {
                    totalHits = peopleCount;
                } else {
                    docCount = peopleCount;
                }
            }
        }

        return new Long[]{new Double(totalHits).longValue(), new Double(docCount).longValue()};
    }

    @Override
    public CommonResultData<List<CommonNameValueVo<Double>>> getReportKeyRate(String areaCode, String indexType, String moveType, String planYear) throws YJHHException {
        DeptBean sysDeptInfo = commonDataComponent.getSysDeptInfo(areaCode);
        if (sysDeptInfo == null) {
            return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
        }
        List<DeptBean> subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());

        int subDeptSize = subDept.size();
        if (subDept == null || subDeptSize <= 0) {
            return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
        }

        //获取最大上报月
        MaxYearMonth maxReportYearMonth = commonDataComponent.getMaxReportYearMonth(null);
        if (maxReportYearMonth == null) {
            return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
        }

        List<CommonNameValueVo<Double>> objRZLVos = new ArrayList<>();
        //获取子部门数据
        for (DeptBean deptBean : subDept) {
            CommonNameValueVo<Double> commonNameValueVo = new CommonNameValueVo<Double>();
            objRZLVos.add(commonNameValueVo);
            commonNameValueVo.setName(deptBean.getDeptName());

            String deptID = deptBean.getDeptID();
            SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("pl_imppr_targetdata").setTypes("imppr_targetdata")
                    .setSize(1000);

            BoolQueryBuilder boolQueryBuilder = boolQuery().must(termQuery("deptid.keyword", deptID));
            boolQueryBuilder.must(termQuery("imptype", moveType));
            boolQueryBuilder.must(termQuery("fillyear", maxReportYearMonth.getYear()));
            boolQueryBuilder.must(termQuery("fillmonth", maxReportYearMonth.getMonth()));
            if (StringUtils.isNotBlank(planYear) && !StringUtils.equalsIgnoreCase(planYear, "all")) {  //all为所有所有计划年
                boolQueryBuilder.must(termQuery("planyear", planYear));          //按计划年进行过滤
            }
            searchRequestBuilder.setQuery(boolQueryBuilder);

            log.info("request=" + searchRequestBuilder.toString());
            SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
            log.info("response=" + searchResponse.toString());

            SearchHit[] searchHits = searchResponse.getHits().getHits();

            if (searchHits == null || searchHits.length <= 0) {
                commonNameValueVo.setValue(0.0);
                continue;
            }

            //indexType:指标类型 (1:开工率;2:竣工率;3:入住率;4:集中安置率)
            Double rate = 0.0;
            switch (indexType) {
                case DataConsts.ReportIndexType.START_RATE:
                    rate = getRate(indexType, moveType, planYear, searchHits, "kg_rate");
                    break;
                case DataConsts.ReportIndexType.END_RATE:
                    rate = getRate(indexType, moveType, planYear, searchHits, "jg_rate");
                    break;
                case DataConsts.ReportIndexType.RZ_RATE:
                    rate = getRate(indexType, moveType, planYear, searchHits, "rz_rate");
                    break;
                case DataConsts.ReportIndexType.JZAZ_RATE:
                    rate = getRate(indexType, moveType, planYear, searchHits, "jzaz_rate");
                    break;
            }
            commonNameValueVo.setValue(rate);
        }
/*
        //入住率由高到低排序
        Collections.sort(objRZLVos, (CommonNameValueVo<Double> o1, CommonNameValueVo<Double> o2) -> {
            return o2.getValue() >= o1.getValue() ? 1 : -1;
        });*/

        return new CommonResultData<>(HttpStatus.OK.value(), "suc", objRZLVos);
    }

    private Double getRate(String indexType, String moveType, String planYear, SearchHit[] searchHits, String keyFieldName) {
        Double rate = 0.0;
        //合计年总任务指标，需要自己计算，已完成的人、户数 除以计划户数
        if (StringUtils.equalsIgnoreCase(planYear, "all")) {
            Long totalPlanCount = 0L;
            Long totalFinishedCount = 0L;
            Long totalKGCount = 0L;   //开工人数/户数
            for (SearchHit searchHit : searchHits) {
                Map<String, Object> searchHitSource = searchHit.getSource();
                //1:合计(按人统计) 2：易地扶贫(按人统计) 3：避灾(按户统计) 4：生态(按户统计)  5:避灾生态合计(按户统计)
                if (StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.ALL, moveType) || StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.YD, moveType)) {
                    totalPlanCount += DataTools.convertToLone(searchHitSource.get("task_rs"));
                } else {
                    totalPlanCount += DataTools.convertToLone(searchHitSource.get("task_hs"));
                }
                switch (indexType) {
                    case DataConsts.ReportIndexType.START_RATE:
                        if (StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.ALL, moveType) || StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.YD, moveType)) {
                            totalFinishedCount += DataTools.convertToLone(searchHitSource.get("kg_rs"));
                        } else {
                            totalFinishedCount += DataTools.convertToLone(searchHitSource.get("kg_hs"));
                        }
                        break;
                    case DataConsts.ReportIndexType.END_RATE:
                        if (StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.ALL, moveType) || StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.YD, moveType)) {
                            totalFinishedCount += DataTools.convertToLone(searchHitSource.get("jg_rs"));
                        } else {
                            totalFinishedCount += DataTools.convertToLone(searchHitSource.get("jg_hs"));
                        }
                        break;
                    case DataConsts.ReportIndexType.RZ_RATE:
                        if (StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.ALL, moveType) || StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.YD, moveType)) {
                            totalFinishedCount += DataTools.convertToLone(searchHitSource.get("rz_rs"));
                        } else {
                            totalFinishedCount += DataTools.convertToLone(searchHitSource.get("rz_hs"));
                        }
                        break;
                    case DataConsts.ReportIndexType.JZAZ_RATE:
                        //集中安置率（合计和易地）= 集中安置的人数 / 开工的人数
                        //集中安置率（避灾、生态、避灾生态合计）= 集中安置的户数 / 开工的户数
                        if (StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.ALL, moveType) || StringUtils.equalsIgnoreCase(DataConsts.ReportMoveType.YD, moveType)) {
                            totalFinishedCount += DataTools.convertToLone(searchHitSource.get("jzaz_rs"));
                            totalKGCount += DataTools.convertToLone(searchHitSource.get("kg_rs"));
                        } else {
                            totalFinishedCount += DataTools.convertToLone(searchHitSource.get("jzaz_hs"));
                            totalKGCount += DataTools.convertToLone(searchHitSource.get("kg_hs"));
                        }
                        break;
                }
            }
            if (totalFinishedCount == 0 || totalPlanCount == 0) {
                rate = 0.0;
            } else {
                BigDecimal bigDecimal;
                if(StringUtils.equalsIgnoreCase(DataConsts.ReportIndexType.JZAZ_RATE,indexType)){
                    bigDecimal = new BigDecimal((totalFinishedCount * 1.0 / totalKGCount * 1.0) * 100);
                }else {
                    bigDecimal = new BigDecimal((totalFinishedCount * 1.0 / totalPlanCount * 1.0) * 100);
                }
                rate = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            }
        } else {
            rate = DataTools.convertToDouble(searchHits[0].getSource().get(keyFieldName));
        }
        return rate;
    }

    @Override
    public CommonResultData<List<Map<String, Object>>> getReportKeyRate(String areaCode) throws YJHHException {
        if (StringUtils.isBlank(areaCode)) {
            return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
        }
        DeptBean sysDeptInfo = commonDataComponent.getSysDeptInfo(areaCode);
        if (sysDeptInfo == null) {
            return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
        }
        List<DeptBean> subDept = commonDataComponent.getSubDeptByDeptId(sysDeptInfo.getDeptID());

        int subDeptSize = subDept.size();
        if (subDept == null || subDeptSize <= 0) {
            return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
        }

        //获取最大上报月
        MaxYearMonth maxReportYearMonth = commonDataComponent.getMaxReportYearMonth(null);
        if (maxReportYearMonth == null) {
            return new CommonResultData<>(HttpStatus.OK.value(), "no data", null);
        }

        List<Map<String, Object>> deptKeyInfoList = new ArrayList<>();
        //获取子部门数据
        for (DeptBean deptBean : subDept) {
            String deptID = deptBean.getDeptID();
            SearchRequestBuilder searchRequestBuilder = esClientManager.getESClient().prepareSearch("pl_imppr_targetdata").setTypes("imppr_targetdata")
                    .setSize(1000);

            BoolQueryBuilder boolQueryBuilder = boolQuery().must(termQuery("deptid.keyword", deptID));
            boolQueryBuilder.must(termQuery("fillyear", maxReportYearMonth.getYear()));
            boolQueryBuilder.must(termQuery("fillmonth", maxReportYearMonth.getMonth()));
            boolQueryBuilder.must(termQuery("imptype", "1"));    //查询合计值
            searchRequestBuilder.setQuery(boolQueryBuilder);

            log.info("request=" + searchRequestBuilder.toString());
            SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
            log.info("response=" + searchResponse.toString());

            SearchHit[] searchHits = searchResponse.getHits().getHits();

            //指标VO
            Map<String, Object> kv = new HashMap<>();
            kv.put("name", deptBean.getDeptName());
            if (searchHits == null || searchHits.length <= 0) {
                kv.put("kg_rate", 0.0);
                kv.put("jg_rate", 0.0);
                kv.put("rz_rate", 0.0);
                kv.put("jzaz_rate", 0.0);
            } else {
                kv.put("kg_rate", getRate("1", "1", "all", searchHits, "kg_rate"));
                kv.put("jg_rate", getRate("2", "1", "all", searchHits, "jg_rate"));
                kv.put("rz_rate", getRate("3", "1", "all", searchHits, "rz_rate"));
                kv.put("jzaz_rate", getRate("4", "1", "all", searchHits, "jzaz_rate"));
            }

            deptKeyInfoList.add(kv);
        }
/*
        //入住率由高到低排序
        Collections.sort(objRZLVos, (CommonNameValueVo<Double> o1, CommonNameValueVo<Double> o2) -> {
            return o2.getValue() >= o1.getValue() ? 1 : -1;
        });*/

        return new CommonResultData<>(HttpStatus.OK.value(), "suc", deptKeyInfoList);
    }
}
